#include "asm_utils.h"
#include "interrupt.h"
#include "stdio.h"
#include "program.h"
#include "thread.h"
#include "sync.h"

// 屏幕IO处理器
STDIO stdio;
// 中断管理器
InterruptManager interruptManager;
// 程序管理器
ProgramManager programManager;

Semaphore chop[5];

void philosopher0(void *arg)
{   
    int delay = 0;
    while(true){
    printf("philosopher0 is thinking\n");
    
    chop[1].P();
    printf("philosopher0 picked up 1\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    chop[0].P();
    printf("philosopher0 picked up 0\n");
    
    printf("philosopher0 is eating,using 0 and 1\n");
    delay = 0x00fffff;
    while(delay){
    	delay--;
    }
    chop[0].V();
    chop[1].V();
    printf("philosopher0 finished eating,put down 0 and 1\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    }
}

void philosopher1(void *arg)
{  
    int delay = 0;
    while(true){
    printf("philosopher1 is thinking\n");
    
    chop[1].P();
    printf("philosopher1 picked up 1\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    chop[2].P();
    printf("philosopher1 picked up 2\n");
    
    printf("philosopher1 is eating,using 1 and 2\n");
     delay = 0x00fffff;
    while(delay){
    	delay--;
    }
    chop[2].V();
    chop[1].V();
    printf("philosopher1 finished eating,put down 1 and 2\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    }
}

void philosopher2(void *arg)
{
    int delay = 0;
    while(true){
    printf("philosopher2 is thinking\n");
    chop[2].P();
    printf("philosopher2 picked up 2\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    chop[3].P();
    printf("philosopher2 picked up 3\n");
    
    printf("philosopher2 is eating,using 2 and 3\n");
     delay = 0x00fffff;
    while(delay){
    	delay--;
    }
    chop[3].V();
    chop[2].V();
    printf("philosopher2 finished eating,put down 2 and 3\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    }
}

void philosopher3(void *arg)
{
    int delay = 0;
    while(true){
    printf("philosopher3 is thinking\n");
    chop[3].P();
    printf("philosopher3 picked up 3\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    chop[4].P();
    printf("philosopher3 picked up 4\n");
    
    printf("philosopher3 is eating,using 3 and 4\n");
    delay = 0x00fffff;
    while(delay){
    	delay--;
    }
    chop[4].V();
    chop[3].V();
    printf("philosopher3 finished eating,put down 3 and 4\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    }
}

void philosopher4(void *arg)
{
    int delay = 0;
    while(true){
    printf("philosopher4 is thinking\n");
    chop[4].P();
    printf("philosopher4 picked up 4\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    chop[0].P();
    printf("philosopher4 picked up 0\n");
    
    printf("philosopher4 is eating,using 4 and 0\n");
    delay = 0x00fffff;
    while(delay){
    	delay--;
    }
    chop[0].V();
    chop[4].V();
    printf("philosopher4 finished eating,put down 4 and 0\n");
    delay = 0x0ffffff;
    while(delay){
    	delay--;
    }
    }
}

void first_thread(void *arg)
{
    // 第1个线程不可以返回
    stdio.moveCursor(0);
    for (int i = 0; i < 25 * 80; ++i)
    {
        stdio.print(' ');
    }
    stdio.moveCursor(0);
    
    for(int i = 0;i < 5;i++){
    	chop[i].initialize(1);
    }

    programManager.executeThread(philosopher0, nullptr, "thread0", 1);
    programManager.executeThread(philosopher1, nullptr, "thread1", 1);
    programManager.executeThread(philosopher2, nullptr, "thread2", 1);
    programManager.executeThread(philosopher3, nullptr, "thread3", 1);
    programManager.executeThread(philosopher4, nullptr, "thread4", 1);

    asm_halt();
}

extern "C" void setup_kernel()
{

    // 中断管理器
    interruptManager.initialize();
    interruptManager.enableTimeInterrupt();
    interruptManager.setTimeInterrupt((void *)asm_time_interrupt_handler);

    // 输出管理器
    stdio.initialize();

    // 进程/线程管理器
    programManager.initialize();

    // 创建第一个线程
    int pid = programManager.executeThread(first_thread, nullptr, "first thread", 1);
    if (pid == -1)
    {
        printf("can not execute thread\n");
        asm_halt();
    }

    ListItem *item = programManager.readyPrograms.front();
    PCB *firstThread = ListItem2PCB(item, tagInGeneralList);
    firstThread->status = RUNNING;
    programManager.readyPrograms.pop_front();
    programManager.running = firstThread;
    asm_switch_thread(0, firstThread);

    asm_halt();
}
